package ovt;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.log4j.Logger;

public class Main extends Thread {
	private static Logger logger = Logger.getLogger(Main.class);
	ConfResolution conf = new ConfResolution();
	public static List<EchoServerThread> threadlist = new ArrayList<EchoServerThread>();
	public static Queue<Queue<SocketChannel>> client_not_completed = new ConcurrentLinkedQueue<Queue<SocketChannel>>();
	private static Selector selector;
//	private static Selector synchronizeselector;
	public static Main threadmain = new Main();
	public static final ReentrantReadWriteLock xmlfilerwlock = new ReentrantReadWriteLock();

	public static void main(String[] args) throws IOException {
		// 服务器重启后，重新生成XML文件、将素材库中的素材文件排序，主要是构造hm和hm_thumbnail，前者存储了所有素材文件夹中的素材文件并按时间新旧排列，后者存储了所有缩略图文件并按时间新旧排列；
		ScanForChange.calculateChanges();
		//构建界面；
		MainFrame mf = new MainFrame();
		mf.start();
		//开启10个用户请求处理线程；
		EchoServerThread esc = new EchoServerThread();
		esc.start();
		threadlist.add(esc);
		EchoServerThread esc1 = new EchoServerThread();
		esc1.start();
		threadlist.add(esc1);
		EchoServerThread esc2 = new EchoServerThread();
		esc2.start();
		threadlist.add(esc2);
		EchoServerThread esc3 = new EchoServerThread();
		esc3.start();
		threadlist.add(esc3);
		EchoServerThread esc4 = new EchoServerThread();
		esc4.start();
		threadlist.add(esc4);
		EchoServerThread esc5 = new EchoServerThread();
		esc5.start();
		threadlist.add(esc5);
		EchoServerThread esc6 = new EchoServerThread();
		esc6.start();
		threadlist.add(esc6);
		EchoServerThread esc7 = new EchoServerThread();
		esc7.start();
		threadlist.add(esc7);
		EchoServerThread esc8 = new EchoServerThread();
		esc8.start();
		threadlist.add(esc8);
		EchoServerThread esc9 = new EchoServerThread();
		esc9.start();
		threadlist.add(esc9);

		selector = Selector.open();
		ServerSocketChannel ssc = ServerSocketChannel.open();
		ssc.configureBlocking(false);
		ServerSocket ss = ssc.socket();
		InetSocketAddress address = new InetSocketAddress(
				ConfResolution.getServerPort());
		ss.bind(address);
		ss.setReuseAddress(true);
		ssc.socket().setReuseAddress(true);
		ssc.register(selector, SelectionKey.OP_ACCEPT);
		
		ServerSocketChannel synchronizessc = ServerSocketChannel.open();
		synchronizessc.configureBlocking(false);
		ServerSocket synchronizess = synchronizessc.socket();
		InetSocketAddress synchronizeaddress = new InetSocketAddress(10001);
		synchronizess.bind(synchronizeaddress);
		synchronizess.setReuseAddress(false);
		synchronizessc.socket().setReuseAddress(false);
		synchronizessc.register(selector, SelectionKey.OP_ACCEPT);
		
		threadmain.start();
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		logger.info("Server start at:" + df.format(new Date()));
	}

	public void run() {
		try {
			while (!Thread.interrupted()) {
				List<EchoServerThread> temp = new ArrayList<EchoServerThread>();
				temp = getDeadThread();
				if (temp != null) {
					logger.debug("Dead thread count:" + temp.size());
					geneNewThread(temp);
				}
				int i = 0;
				//每个线程如果中途出现异常导致还有用户请求没有完成，在这里将未处理完成的用户请求分配到其他线程中去。
				if (client_not_completed.size() > 0) {
					Iterator<Queue<SocketChannel>> iter1 = client_not_completed
							.iterator();
					while (iter1.hasNext()) {
						Queue<SocketChannel> undonelistperthread = iter1.next();
						logger.debug("Select new msgThread for one dead thread");
						if (undonelistperthread.size() > 0) {
							Iterator<SocketChannel> iter2 = undonelistperthread
									.iterator();
							while (iter2.hasNext()) {
								SocketChannel sc = iter2.next();
								findSuitableThread(sc);
								i++;
							}
						}
					}
					logger.debug("Interrupted Client number = " + i
							+ ", and has selected new msgThread for them.");
					client_not_completed.clear();
				}

				if (selector.select() > 0) {
					Set<SelectionKey> selectionKeys = selector.selectedKeys();
					Iterator<SelectionKey> iter = selectionKeys.iterator();
					SocketChannel sc;
					while (iter.hasNext()) {
						SelectionKey key = iter.next();
						if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {
							ServerSocketChannel subssc = (ServerSocketChannel) key
									.channel();
							sc = subssc.accept();
							sc.configureBlocking(false);
							sc.register(selector, SelectionKey.OP_READ);
							findSuitableThread(sc);
							iter.remove();
						}
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
			logger.error("Wrong in main. IOException.");
		}
		logger.info("EXIT Main Thread(Select msgThread Thread)");
	}

	/** 遍历10个线程，取得dead线程
	 * @return dead线程的list
	 */
	public static ArrayList<EchoServerThread> getDeadThread() {
		List<EchoServerThread> temp = new ArrayList<EchoServerThread>();
		Iterator<EchoServerThread> iter = threadlist.iterator();
		while (iter.hasNext()) {
			EchoServerThread est = iter.next();
			if (!est.isAlive()) {
				temp.add(est);
			}
		}
		if (temp.size() != 0) {
			return (ArrayList<EchoServerThread>) temp;
		} else
			return null;
	}

	/**
	 * 从threadlist中撤销死亡线程，生成新线程加入到threadlist中
	 * 
	 * @param temp 死亡线程的个数
	 */
	public static void geneNewThread(List<EchoServerThread> temp) {
		int deadcount = temp.size();
		Iterator<EchoServerThread> iter = temp.iterator();
		while (iter.hasNext()) {
			EchoServerThread est = iter.next();
			if (threadlist.contains(est)) {
				threadlist.remove(est);
			}
		}
		if (deadcount >= 0) {
			for (int i = 0; i < deadcount; i++) {
				EchoServerThread estt = new EchoServerThread();
				estt.start();
				threadlist.add(estt);
				logger.debug("Generate one new thread, and the ID = "
						+ estt.getId());
			}
		}
	}

	/** 为未完成的socketchannel分配新线程；
	 * @param sc
	 */
	public static void findSuitableThread(SocketChannel sc) {
		int index = 0;
		int imin = 0;
		EchoServerThread minthread = null;
		for (EchoServerThread thread : threadlist) {
			if (!thread.isAlive()) {
				continue;
			}
			int ithis = thread.client_count.intValue();
			if (index == 0) {
				imin = ithis;
				minthread = thread;
			} else {
				if (ithis < imin) {
					imin = ithis;
					minthread = thread;
				}
			}
			index++;
		}
		minthread.addclient(sc);
		logger.debug("Selected Thread ID = " + minthread.getId()
				+ " Selected Thread Name = " + minthread.getName()
				+ ",This thread has " + imin + " clients now");
	}

	public void forDeadThread(Queue<SocketChannel> queue) {
		synchronized (client_not_completed) {
			client_not_completed.add(queue);
		}
	}
}
